package com.hujing.mongodb.util;

import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.GroupOperation;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * Mongo数据库的操作类
 */
public class MongoTemplateUtil {

    private final static String HOST = "localhost";
    private final static int PORT = 27017;
    private final static String DB = "test";
    private final static String USERNAME = "";
    private final static String PASSWORD = "";

    private static MongoTemplate mongoTemplate;

    static {
        // 构建Mongo连接字符串
        try {
            String conStr = String.format("mongodb://%s:%d/%s", HOST, PORT, DB);
            //初始化MongoClient,MongoTemplate
            MongoClient mongoClient = MongoClients.create(conStr);
            mongoTemplate = new MongoTemplate(mongoClient, DB);
            System.out.println("初始化MongoTemplate成功");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    // 新增单个实体
    public static <T> T insert(T entity) {
        return mongoTemplate.insert(entity);
    }

    // 批量新增实体
    public static <T> List<T> batchInsert(List<T> list) {
        return (List<T>) mongoTemplate.insertAll(list);
    }

    // 根据id查询单个实体
    public static <T> Optional<T> findById(String id, Class<T> clazz) {
        T entity = mongoTemplate.findById(id, clazz);
        return Optional.ofNullable(entity);
    }

    // 查询所有数据
    public static <T> List<T> findAll(Class<T> clazz) {
        return mongoTemplate.findAll(clazz);
    }

    // 条件查询
    public static <T> List<T> findByCriteria(Criteria criteria, Class<T> clazz) {
        Query query = new Query(criteria);
        return mongoTemplate.find(query, clazz);
    }

    // 条件分页查询
    public static <T> List<T> findByPage(Criteria criteria, int pageNum, int pageSize, Class<T> clazz) {
        Query query = new Query(criteria).skip((long) (pageNum - 1) * pageSize).limit(pageSize);
        return mongoTemplate.find(query, clazz);
    }
    
    // 复杂聚合查询，按性别分组，统计人数，平均年龄，最大年龄
    public static List<Map> groupByGender(){
        // 按性别分组，计算统计字段
        GroupOperation group = Aggregation.group("gender")
                .count().as("userCount")
                .avg("age").as("avgAge")
                .max("age").as("maxAge")
                .min("age").as("minAge");
        
        // 构建聚合管道
        Aggregation aggregation = Aggregation.newAggregation(group);
        
        // 执行聚合查询
        AggregationResults<Map> result = mongoTemplate.aggregate(aggregation, TestUser.class, Map.class);
        
        return result.getMappedResults();
    }

    public static void main(String[] args) {
        // 新增数据
//        TestUser testUser = new TestUser("张三", 25, "男");
//        TestUser saveUser = insert(testUser);
//        System.out.println("新增成功:"+saveUser);
//        String id = saveUser.getId();

        // 批量新增数据
//        List<TestUser> list = new ArrayList<>();
//        list.add(new TestUser("李四", 26, "男"));
//        list.add(new TestUser("王五", 26, "男"));
//        list.add(new TestUser("赵六", 27, "男"));
//        List<TestUser> testUsers = batchInsert(list);
//        System.out.println("批量新增成功:"+testUsers);

        // 根据id查询数据
//        Optional<TestUser> testUser = findById("6919a860a028c17d72589f2c", TestUser.class);
//        testUser.ifPresent(e-> System.out.println("根据id查询结果："+testUser));

        // 查询所有数据
//        List<TestUser> all = findAll(TestUser.class);
//        System.out.println("查询所有数据："+all);

        // 查询年龄是26的用户
//        Criteria criteria = Criteria.where("age").is(26);
//        List<TestUser> result = findByCriteria(criteria, TestUser.class);
//        System.out.println("年龄是26的用户：" + result);
        
        // 条件分页查询，查询第1页，每页2条
        Criteria criteria = new Criteria();
        List<TestUser> result = findByPage(criteria, 1, 2, TestUser.class);
        System.out.println("条件分页查询结果："+result);
    }

    // 定义自测实体类
    @Document(collection = "test_user")
    public static class TestUser {
        @Id
        private String id;
        private String name;
        private Integer age;
        private String gender;
        private LocalDateTime createTime;

        public TestUser() {
        }

        public TestUser(String name, Integer age, String gender) {
            this.name = name;
            this.age = age;
            this.gender = gender;
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Integer getAge() {
            return age;
        }

        public void setAge(Integer age) {
            this.age = age;
        }

        public String getGender() {
            return gender;
        }

        public void setGender(String gender) {
            this.gender = gender;
        }

        public LocalDateTime getCreateTime() {
            return createTime;
        }

        public void setCreateTime(LocalDateTime createTime) {
            this.createTime = createTime;
        }

        @Override
        public String toString() {
            return "TestUser{" +
                    "id='" + id + '\'' +
                    ", name='" + name + '\'' +
                    ", age=" + age +
                    ", gender='" + gender + '\'' +
                    ", createTime=" + createTime +
                    '}';
        }
    }

}
